#pragma once

#include "logmessage.hpp"
#include <string>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class UdpClient
{
    int _sockfd;
    std::string _serverip;
    uint16_t _serverport;
    bool _quit;

public:
    UdpClient(const std::string &ip, const uint16_t port)
        : _serverip(ip),
          _serverport(port),
          _sockfd(-1),
          _quit(false)
    {
    }

    void InitClient()
    {
        // 1.创建套接字文件描述符
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd == -1)
        {
            LogMessage(FATAL, "(%d)%s", errno, strerror(errno));
            exit(errno);
        }
        // 2.不需要显示绑定IP和端口号，OS会自动绑定

        LogMessage(DEBUG, "init client success!");
    }

    void SendMsg()
    {
        sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_port = htons(_serverport);
        server.sin_addr.s_addr = inet_addr(_serverip.c_str());
        char buffer[1024] = "login";
        bool first = true;

        while (!_quit)
        {
            if (!first)
            {
                printf("Please Enter$ ");
                fgets(buffer, sizeof(buffer), stdin);
                buffer[strlen(buffer) - 1] = '\0'; // 删除换行符
            }
            first = false;
            if (strcmp(buffer, "quit") == 0)
            {
                _quit = true;
            }
            if (strlen(buffer) < 1)
                continue;
            // 当client首次给server发送数据时，OS会自动给client绑定IP地址和端口号
            ssize_t s = sendto(_sockfd, buffer, strlen(buffer), 0, (sockaddr *)&server, sizeof(server));
            if (s == -1)
            {
                LogMessage(ERROR, "(%d)%s", errno, strerror(errno));
                continue;
            }
        }
    }

    void RecvMsg()
    {
        char buffer[1024];

        while (!_quit)
        {
            // sockaddr_in temp;
            // memset(&temp, 0, sizeof(temp));
            // socklen_t len = sizeof(temp);
            // ssize_t s = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr *)&temp, &len);
            ssize_t s = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, nullptr, nullptr);
            if (s > 0)
            {
                buffer[s] = 0;
                fprintf(stderr, "%s\n");
            }
        }
    }

    ~UdpClient()
    {
        if (_sockfd >= 0)
            close(_sockfd);
    }
};
